package club.zhilin.guli.service.edu.service.impl;

import club.zhilin.guli.common.base.result.CommonResult;
import club.zhilin.guli.service.base.exception.GlobalException;
import club.zhilin.guli.service.edu.domain.*;
import club.zhilin.guli.service.edu.domain.dto.CourseDTO;
import club.zhilin.guli.service.edu.domain.qo.CourseQueryObject;
import club.zhilin.guli.service.edu.domain.qo.PortalCourseQueryObject;
import club.zhilin.guli.service.edu.domain.vo.CourseRelation;
import club.zhilin.guli.service.edu.domain.vo.CourseVO;
import club.zhilin.guli.service.edu.feign.OssFileService;
import club.zhilin.guli.service.edu.mapper.*;
import club.zhilin.guli.service.edu.service.ICourseDescriptionService;
import club.zhilin.guli.service.edu.service.ICourseService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author zhilin
 * @since 2022-01-11 15:29:01
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    private final ICourseDescriptionService iCourseDescriptionService;
    private final OssFileService ossFileService;
    private final ChapterMapper chapterMapper;
    private final CommentMapper commentMapper;
    private final VideoMapper videoMapper;
    private final CourseCollectMapper courseCollectMapper;

    @Override
    public String saveCourse(CourseVO courseVO) {
        Course course = new Course();
        BeanUtils.copyProperties(courseVO, course);
        course.setStatus(true);
        this.save(course);
        CourseDescription description = new CourseDescription();
        description.setDescription(courseVO.getDescription());
        description.setId(course.getId());
        iCourseDescriptionService.save(description);
        return course.getId();
    }

    @Override
    public CommonResult<CourseVO> selectCourseById(String id) {
        Course course = this.getById(id);
        CourseDescription description = iCourseDescriptionService.getById(id);
        if (course == null || description == null) {
            return CommonResult.failed("未查询到您需要的数据");
        }
        CourseVO courseVO = new CourseVO();
        BeanUtils.copyProperties(course, courseVO);
        courseVO.setDescription(description.getDescription());
        return CommonResult.success(courseVO);
    }

    @Override
    public CommonResult<String> updateCourseVo(CourseVO courseVO) {
        Course course = new Course();
        BeanUtils.copyProperties(courseVO, course);
        this.updateById(course);
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(courseVO.getDescription());
        courseDescription.setId(courseVO.getId());
        iCourseDescriptionService.updateById(courseDescription);
        return CommonResult.success("更新成功");
    }

    @Override
    public CommonResult<Map<String, Object>> selectList(Long page, Long limit, CourseQueryObject courseQueryObject) {
        // 显示分页列表
        Map<String, Object> result = new HashMap<>(2);
        Page<CourseDTO> condition = new Page<>(page, limit);
        QueryWrapper<Course> wrapper = new QueryWrapper<>();
        wrapper = wrapper.orderByDesc("c.gmt_create");
        if (courseQueryObject != null) {
            if (StringUtils.isNotEmpty(courseQueryObject.getTitle())) {
                wrapper.like("c.title", courseQueryObject.getTitle());
            }
            if (StringUtils.isNotEmpty(courseQueryObject.getSubjectId())) {
                wrapper.eq("c.subject_id", courseQueryObject.getSubjectId());
            }
            if (StringUtils.isNotEmpty(courseQueryObject.getSubjectParentId())) {
                wrapper.eq("c.subject_parent_id", courseQueryObject.getSubjectParentId());
            }
            if (StringUtils.isNotEmpty(courseQueryObject.getTeacherId())) {
                wrapper.eq("c.teacher_id", courseQueryObject.getTeacherId());
            }
        }
        // 只需要在mapper层传入封装好的分页组件,sql
        List<CourseDTO> list = baseMapper.selectPageByCourseQueryVo(condition, wrapper);
        condition.setRecords(list);
        result.put("total", condition.getTotal());
        result.put("rows", list);
        return CommonResult.success(result);
    }

    @Override
    public boolean removeCoverById(String id) {
        Course course = baseMapper.selectOne(new LambdaQueryWrapper<Course>().select(Course::getCover).eq(Course::getId, id));
        if (course != null) {
            String cover = course.getCover();
            if (StringUtils.isNotEmpty(cover)) {
                CommonResult<String> result = ossFileService.deleteFile(cover);
                return result.isSuccess();
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeCoverByCourseId(String id) {
        // 根据courseId删除video(视频)
        videoMapper.delete(new LambdaQueryWrapper<Video>().eq(Video::getCourseId, id));
        // 根据courseId删除chapter(章节)
        chapterMapper.delete(new LambdaQueryWrapper<Chapter>().eq(Chapter::getCourseId, id));
        // 根据courseId删除comment
        commentMapper.delete(new LambdaQueryWrapper<Comment>().eq(Comment::getCourseId, id));
        // 根据courseId删除courseCollect(收藏)
        courseCollectMapper.delete(new LambdaQueryWrapper<CourseCollect>().eq(CourseCollect::getCourseId, id));
        // 根据courseId删除courseDescription(课程描述)
        iCourseDescriptionService.removeById(id);
        // 根据courseId删除course
        return this.removeById(id);
    }

    @Override
    public List<Course> selectListByCondition(PortalCourseQueryObject portalCourseQueryObject) {
        LambdaQueryWrapper<Course> wrapper = null;
        if (portalCourseQueryObject != null) {
            wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Course::getStatus, true);
            if (StringUtils.isNotEmpty(portalCourseQueryObject.getSubjectParentId())) {
                wrapper.eq(Course::getSubjectParentId, portalCourseQueryObject.getSubjectParentId());
            }
            if (StringUtils.isNotEmpty(portalCourseQueryObject.getSubjectId())) {
                wrapper.eq(Course::getSubjectId, portalCourseQueryObject.getSubjectId());
            }
            if (StringUtils.isNotEmpty(portalCourseQueryObject.getSortName())) {
                switch (portalCourseQueryObject.getSortName()) {
                    case "buyCount":
                        wrapper.orderBy(true, "asc".equals(portalCourseQueryObject.getSortValue()), Course::getBuyCount);
                        break;
                    case "gmtCreate":
                        wrapper.orderBy(true, "asc".equals(portalCourseQueryObject.getSortValue()), Course::getGmtCreate);
                        break;
                    case "price":
                        wrapper.orderBy(true, "asc".equals(portalCourseQueryObject.getSortValue()), Course::getPrice);
                        break;
                    default:
                }
            }
        }
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CourseRelation selectCourseRelation(String courseId) {
        Course course = this.baseMapper.selectById(courseId);
        // 更新浏览量
        course.setViewCount(course.getViewCount() + 1);
        // 更新
        this.baseMapper.updateById(course);
        // 获取更新操作
        return baseMapper.selectCourseRelation(courseId);
    }

    @Override
    @Cacheable(value = "index", key = "'selectHotCourse'")
    public List<Course> selectHotCourse() {
        return baseMapper.selectList(new LambdaQueryWrapper<Course>().orderByDesc(Course::getViewCount).last("limit 8"));
    }

    @Override
    public club.zhilin.guli.service.base.dto.CourseDTO selectCourseDTO(String courseId) {
        club.zhilin.guli.service.base.dto.CourseDTO courseDTO = baseMapper.selectCourseDTO(courseId);
        if (courseDTO == null) {
            throw new GlobalException("没有查询到指定记录");
        }
        return courseDTO;
    }

    @Override
    public void updateBuyCountByCourseId(String courseId) {
        Course course = this.getById(courseId);
        course.setBuyCount(course.getBuyCount() + 1);
        this.updateById(course);
    }

    @Override
    public Integer selectCoursePublishCount(String date) {
        return baseMapper.selectCoursePublishCount(date);
    }
}
